home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / server / input.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  53KB  |  1,965 lines

  1. /*
  2.  * static char *rcsid_input_c =
  3.  *   "$Id: input.c,v 1.54 1996/07/24 07:39:18 master Exp master $";
  4.  */
  5. /*
  6.     CrossFire, A Multiplayer game for X-windows
  7.  
  8.     Copryight (C) 1994 Mark Wedel
  9.     Copyright (C) 1992 Frank Tore Johansen
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 2 of the License, or
  14.     (at your option) any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.     The author can be reached via e-mail to master@rahul.net
  26. */
  27.  
  28. #include <global.h>
  29. #ifndef __CEXTRACT__
  30. #include <sproto.h>
  31. #endif
  32. #include <version.h>
  33. #include <main.h>
  34. #include <spells.h>
  35. #include <newclient.h>
  36.  
  37. #ifdef SET_TITLE
  38. extern void redraw_title(object *pl);
  39. #endif /* SET_TITLE */
  40.  
  41. int onoff_value(char *line)
  42. {
  43.   int i;
  44.  
  45.   if (sscanf(line, "%d", &i))
  46.     return (i != 0);
  47.   switch (line[0]) {
  48.   case 'o':
  49.     switch (line[1]) {
  50.     case 'n': return 1;        /* on */
  51.     default:  return 0;        /* o[ff] */
  52.     }
  53.   case 'y':            /* y[es] */
  54.   case 'k':            /* k[ylla] */
  55.   case 's':
  56.   case 'd':
  57.     return 1;
  58.   case 'n':            /* n[o] */
  59.   case 'e':            /* e[i] */
  60.   case 'u':
  61.   default:
  62.     return 0;
  63.   }
  64. }
  65.  
  66. /*
  67.  * flags:
  68.  *  0 - inv & below
  69.  *  1 - below & inv
  70.  *  2 - inv
  71.  *  3 - below
  72.  */
  73. object **find_objects(object *op, char *line, int flags)
  74. {
  75.  
  76.   return NULL;
  77. }
  78.  
  79. /*
  80.  * Check if an item op can be put into a sack. If pl exists then tell
  81.  * a player the reason of failure.
  82.  * returns 1 if it will fit, 0 if it will not.  nrof is the number of
  83.  * objects (op) we want to put in.  We specify it separately instead of
  84.  * using op->nrof because often times, a player may have specified a
  85.  * certain number of objects to drop, so we can pass that number, and
  86.  * not need to use split_ob and stuff.
  87.  */
  88. int sack_can_hold (object *pl, object *sack, object *op, int nrof) {
  89.     char buf[MAX_BUF];
  90.     buf[0] = 0;
  91.  
  92.     if (! QUERY_FLAG (sack, FLAG_APPLIED))
  93.     sprintf (buf, "%s is not active.", query_name(sack));
  94.     if (sack == op)
  95.     sprintf (buf, "You can't put %s into itself.", query_name(sack));
  96.     if (sack->race && (sack->race != op->race || op->type == CONTAINER
  97.                || (sack->stats.food && sack->stats.food != op->type)))
  98.     sprintf (buf, "You can put only %s into %s.", sack->race,
  99.          query_name(sack));
  100.     if (op->type == SPECIAL_KEY && sack->slaying && op->slaying)
  101.     sprintf (buf, "You don't want put the key into %s.", query_name(sack));
  102.     if (sack->weight_limit && sack->carrying + (nrof ? nrof : 1) * 
  103.     op->weight * (100 - sack->stats.Str) / 100  > sack->weight_limit)
  104.     sprintf (buf, "That won't fit in %s!", query_name(sack));
  105.     if (buf[0]) {
  106.     if (pl)
  107.         new_draw_info(NDI_UNIQUE, 0,pl, buf);
  108.     return 0;
  109.     }
  110.     return 1;
  111. }
  112.  
  113.  
  114. void lock_inv(object *op, object *item) {
  115.   SET_FLAG(item,FLAG_INV_LOCKED);
  116.   new_draw_info(NDI_UNIQUE, 0,op,"Item has been locked");
  117.   draw_inventory(op);
  118.   return;
  119. }
  120.  
  121. void unlock_inv(object *op, object *item) {
  122.   CLEAR_FLAG(item,FLAG_INV_LOCKED);
  123.   new_draw_info(NDI_UNIQUE, 0,op,"Item has been unlocked");
  124.   draw_inventory(op);
  125.   return;
  126. }
  127.  
  128.  
  129. /* Eneq(@csd.uu.se): Had to remove rotate_right and replace it with a version
  130.    which doesn't use insert_ob_in_ob since I redid that to add things last in
  131.    the inventory, or next to objects of it's own type. This one now works just
  132.    like rotate_left but reversed :-) 
  133.    [ And now handles invisible objects. Tero.Haatanen@lut.fi ] */
  134.  
  135. void rotate_right(object *op) {
  136.   object *tmp;
  137.   char buf[MAX_BUF];
  138.   int items=0;
  139.  
  140.   for (tmp=op->inv;tmp;tmp=tmp->below)
  141.     if (!tmp->invisible)
  142.       items++;
  143.  
  144.   if(items==0) {
  145.     new_draw_info(NDI_UNIQUE, 0,op,"You don't carry anything.");
  146.     return;
  147.   }
  148.   if(items==1) {
  149.     new_draw_info(NDI_UNIQUE, 0,op,"You only carry one thing.");
  150.     return;
  151.   }
  152.   op->contr->last_used=NULL;
  153.   op->contr->last_used_id=0;
  154.   for (tmp=op->inv; tmp && tmp->below; tmp=tmp->below);
  155.   while(tmp!=NULL&&tmp->invisible)
  156.     tmp=tmp->above;
  157.   /* tmp points now the last visible item in the inventory */
  158.   tmp->above->below=tmp->below;
  159.   if (tmp->below)
  160.     tmp->below->above=tmp->above;
  161.   tmp->above=NULL;
  162.   tmp->below=op->inv;
  163.   op->inv->above=tmp;
  164.   op->inv=tmp;
  165.  
  166.   if(QUERY_FLAG(op, FLAG_WIZ))
  167.     sprintf(buf,"The %s (%d) is now on top.",
  168.             query_name(op->inv),op->inv->count);
  169.   else
  170.     sprintf(buf,"The %s is now on top.",query_name(op->inv));
  171.   new_draw_info(NDI_UNIQUE, 0,op,buf);
  172.   draw_inventory(op);
  173. }
  174.  
  175. /*
  176.  * [ Now rotate_left handles invisible objects too. Tero.Haatanen@lut.fi ]
  177.  */
  178.  
  179. void rotate_left(object *op) {
  180.   object *tmp,*tmp2;
  181.   char buf[MAX_BUF];
  182.   int items=0;
  183.  
  184.   for (tmp=op->inv;tmp;tmp=tmp->below)
  185.     if (!tmp->invisible)
  186.       items++;
  187.  
  188.   if(items==0) {
  189.     new_draw_info(NDI_UNIQUE, 0,op,"You don't carry anything.");
  190.     return;
  191.   }
  192.   if(items==1) {
  193.     new_draw_info(NDI_UNIQUE, 0,op,"You only carry one thing.");
  194.     return;
  195.   }
  196.   op->contr->last_used=NULL;
  197.   op->contr->last_used_id=0;
  198.   for (tmp=op->inv; tmp && tmp->below; tmp=tmp->below);
  199.   for (tmp2=op->inv->below; tmp2 && tmp2->invisible; tmp2=tmp2->below);
  200.  
  201.   tmp2->above->below=NULL;
  202.   tmp2->above=NULL;
  203.   tmp->below=op->inv;
  204.   op->inv->above=tmp;
  205.   op->inv=tmp2;
  206.  
  207.   if(QUERY_FLAG(op, FLAG_WIZ))
  208.     sprintf(buf,"The %s (%d) is now on top.",
  209.             query_name(op->inv),op->inv->count);
  210.   else
  211.     sprintf(buf,"The %s is now on top.",query_name(op->inv));
  212.   new_draw_info(NDI_UNIQUE, 0,op,buf);
  213.   draw_inventory(op);
  214. }
  215.  
  216. void apply_inventory(object *op) {
  217.   object *inv;
  218.   if(op->contr->last_used!=NULL) {
  219.     inv=op->contr->last_used;
  220.     if(QUERY_FLAG(inv, FLAG_FREED)||inv->count!=op->contr->last_used_id||
  221.        inv->env==NULL||(inv->env!=op&&inv->env->env!=op)) {
  222.       op->contr->last_used=NULL;
  223.       op->contr->last_used_id=0;
  224.       apply_inventory(op);
  225.       return;
  226.     }
  227.   } else {
  228.     inv= op->inv;
  229.     while(inv&&inv->invisible)
  230.       inv=inv->below;
  231.   }
  232.   if(inv) {
  233.     if(!apply(op,inv)) {
  234.       new_draw_info_format(NDI_UNIQUE, 0, op,
  235.     "I don't know how to apply the %s.",query_name(inv));
  236.     }
  237.   } else {
  238.     new_draw_info(NDI_UNIQUE, 0,op, "You have nothing to apply!");
  239.   }
  240. }
  241.  
  242. void drop_inventory(object *op) {
  243.   object *inv,*n=NULL;
  244.   if(op->contr->last_used!=NULL) {
  245.     inv=op->contr->last_used;
  246.     if(QUERY_FLAG(inv, FLAG_FREED)||inv->count!=op->contr->last_used_id||
  247.        inv->env==NULL||(inv->env!=op&&inv->env->env!=op)) {
  248.       op->contr->last_used=NULL;
  249.       op->contr->last_used_id=0;
  250.       drop_inventory(op);
  251.       return;
  252.     }
  253.     inv=op->contr->last_used;
  254.     if(inv->below!=NULL)
  255.       n=inv->below;
  256.     else if(inv->above!=NULL)
  257.       n=inv->above;
  258.     if(n!=NULL) {
  259.       op->contr->last_used=n;
  260.       op->contr->last_used_id=n->count;
  261.     }
  262.   } else {
  263.     inv=op->inv;
  264.     while(inv&&inv->invisible)
  265.       inv=inv->below;
  266.   }
  267.   if(inv)
  268.     drop(op,inv);
  269.   else
  270.     new_draw_info(NDI_UNIQUE, 0,op,"You have nothing to drop!");
  271. }
  272.  
  273.  
  274. void examine_monster(object *op,object *tmp) {
  275.   object *mon=tmp->head?tmp->head:tmp;
  276.   archetype *at=tmp->arch;
  277.   if(QUERY_FLAG(mon,FLAG_UNDEAD))
  278.     new_draw_info(NDI_UNIQUE, 0,op,"It is an undead force.");
  279.   if(mon->level>op->level)
  280.     new_draw_info(NDI_UNIQUE, 0,op,"It is likely more powerful than you.");
  281.   else if(mon->level<op->level)
  282.     new_draw_info(NDI_UNIQUE, 0,op,"It is likely less powerful than you.");
  283.   else
  284.     new_draw_info(NDI_UNIQUE, 0,op,"It is probably as powerful as you.");
  285.   if(mon->attacktype&AT_ACID)
  286.     new_draw_info(NDI_UNIQUE, 0,op,"You seem to smell an acrid odor.");
  287.   if(tmp->type!=PLAYER)
  288.     return;
  289.   switch((mon->stats.hp+1)*4/(at->clone.stats.hp+1)) { /* From 1-4 */
  290.   case 1:
  291.     new_draw_info(NDI_UNIQUE, 0,op,"It is in a bad shape.");
  292.     break;
  293.   case 2:
  294.     new_draw_info(NDI_UNIQUE, 0,op,"It is hurt.");
  295.     break;
  296.   case 3:
  297.     new_draw_info(NDI_UNIQUE, 0,op,"It is somewhat hurt.");
  298.     break;
  299.   case 4:
  300.     new_draw_info(NDI_UNIQUE, 0,op,"It is in excellent shape.");
  301.     break;
  302.   }
  303.   if(present_in_ob(POISONING,mon)!=NULL)
  304.     new_draw_info(NDI_UNIQUE, 0,op,"It looks very ill.");
  305. }
  306.  
  307. char *long_desc(object *tmp) {
  308.   static char buf[MAX_BUF];
  309.   char *cp;
  310.   if(tmp==NULL)
  311.     return "";
  312.   buf[0]='\0';
  313.   switch(tmp->type) {
  314.   case RING:
  315.   case SKILL:
  316.   case WEAPON:
  317.   case ARMOUR:
  318.   case BRACERS:
  319.   case HELMET:
  320.   case SHIELD:
  321.   case BOOTS:
  322.   case GLOVES:
  323.   case AMULET:
  324.   case GIRDLE:
  325.   case BOW:
  326.   case ARROW:
  327.   case CLOAK:
  328.     if(*(cp=describe_item(tmp))!='\0')
  329.       sprintf(buf,"%s %s",query_name(tmp),cp);
  330.     break;
  331.   }
  332.   if(buf[0]=='\0')
  333.     sprintf(buf,"%s",query_name(tmp));
  334.  
  335.   return buf;
  336. }
  337.  
  338. void examine(object *op, object *tmp) {
  339.   char buf[MAX_BUF];
  340.  
  341.   if (tmp == NULL || tmp->type == CLOSE_CON)
  342.     return;
  343. /* Eneq(csd.uu.se): If NO_PRETEXT is defined we should only print the name. */
  344.   if (QUERY_FLAG(tmp, FLAG_NO_PRETEXT))
  345.     sprintf(buf, "%s.", long_desc(tmp));
  346.   else
  347.     sprintf(buf, "That is %s.", long_desc(tmp));
  348.   new_draw_info(NDI_UNIQUE, 0,op,buf);
  349.   buf[0]='\0';
  350.   switch(tmp->type) {
  351.   case SPELLBOOK:
  352.     if(QUERY_FLAG(tmp, FLAG_IDENTIFIED) && tmp->stats.sp > 0 && tmp->stats.sp <= NROFREALSPELLS )
  353.       if(!strcmp(tmp->arch->name,"cleric_book"))
  354.         sprintf(buf,"%s is a %d level prayer.",
  355.               spells[tmp->stats.sp].name,spells[tmp->stats.sp].level);
  356.       else
  357.         sprintf(buf,"%s is a %d level spell.",
  358.               spells[tmp->stats.sp].name,spells[tmp->stats.sp].level);
  359.     break;
  360.   case BOOK:
  361.     if(tmp->msg!=NULL)
  362.       strcpy(buf,"Something is written in it.");
  363.     break;
  364.   case CONTAINER:
  365.     if(tmp->race!=NULL)
  366.       if(tmp->weight_limit && tmp->stats.Str<100)
  367.         sprintf (buf,"It can hold only %s and its weight limit is %.1f kg.", 
  368.          tmp->race, tmp->weight_limit/(10.0 * (100 - tmp->stats.Str)));
  369.       else
  370.         sprintf (buf,"It can hold only %s.", tmp->race);
  371.     else
  372.       if(tmp->weight_limit && tmp->stats.Str<100)
  373.         sprintf (buf,"Its weight limit is %.1f kg.", 
  374.         tmp->weight_limit/(10.0 * (100 - tmp->stats.Str)));
  375.     break;
  376.   case WAND:
  377.     if(QUERY_FLAG(tmp, FLAG_IDENTIFIED))
  378.       sprintf(buf,"It has %d charges left.",tmp->stats.food);
  379.     break;
  380.   }
  381.   if(buf[0]!='\0')
  382.     new_draw_info(NDI_UNIQUE, 0,op,buf);
  383.   if(tmp->material) {
  384.     strcpy(buf,"It is made of: ");
  385.     if(tmp->material&M_PAPER)
  386.       strcat(buf,"paper ");
  387.     if(tmp->material&M_IRON)
  388.       strcat(buf,"iron ");
  389.     if(tmp->material&M_GLASS)
  390.       strcat(buf,"glass ");
  391.     if(tmp->material&M_LEATHER)
  392.       strcat(buf,"leather ");
  393.     if(tmp->material&M_WOOD)
  394.       strcat(buf,"wood ");
  395.     if(tmp->material&M_ORGANIC)
  396.       strcat(buf,"organics ");
  397.     if(tmp->material&M_STONE)
  398.       strcat(buf,"stone ");
  399.     if(tmp->material&M_CLOTH)
  400.       strcat(buf,"cloth ");
  401.     if(tmp->material&M_ADAMANT)
  402.       strcat(buf,"adamantite ");
  403.     new_draw_info(NDI_UNIQUE, 0,op,buf);
  404.   }
  405.   if(tmp->weight) {
  406.     sprintf(buf,"%s weighs %3.3f kg.", tmp->nrof>1?"They":"It",
  407.             (tmp->nrof?tmp->weight*tmp->nrof:tmp->weight)/1000.0);
  408.     new_draw_info(NDI_UNIQUE, 0,op,buf);
  409.   }
  410.   if(tmp->value&&!QUERY_FLAG(tmp, FLAG_STARTEQUIP)) {
  411.     if(QUERY_FLAG(tmp, FLAG_UNPAID))
  412.       sprintf(buf,"%s would cost you %s.",
  413.               tmp->nrof>1?"They":"It",query_cost_string(tmp,op,F_BUY));
  414.     else
  415.       sprintf(buf,"You would get %s for %s.",
  416.               query_cost_string(tmp,op,F_SELL), tmp->nrof>1?"them":"it");
  417.     new_draw_info(NDI_UNIQUE, 0,op,buf);
  418.   }
  419.   if(QUERY_FLAG(tmp, FLAG_MONSTER))
  420.     examine_monster(op,tmp);
  421.   if(tmp->msg && tmp->type != EXIT && tmp->type != BOOK && tmp->type != CORPSE
  422.      && !QUERY_FLAG(tmp, FLAG_WALK_ON)) {
  423.     if (need_identify(tmp) && QUERY_FLAG(tmp, FLAG_IDENTIFIED))
  424.       new_draw_info(NDI_UNIQUE, 0,op, "The object has a story:");
  425. #if 0 /* it might not be written on it */
  426.     else
  427.       new_draw_info(NDI_UNIQUE, 0,op,"Something is written on it:");
  428. #endif
  429.     new_draw_info(NDI_UNIQUE, 0,op,tmp->msg);
  430.   }
  431.   new_draw_info(NDI_UNIQUE, 0,op," "); /* Blank line */
  432. }
  433.  
  434. /*
  435.  * inventory prints object's inventory. If inv==NULL then print player's
  436.  * inventory. 
  437.  * [ Only items which are applied are showed. Tero.Haatanen@lut.fi ]
  438.  */
  439. void inventory(object *op,object *inv) {
  440.   object *tmp;
  441.   char buf[MAX_BUF], *in;
  442.   int items = 0, length;
  443.  
  444.   if (inv==NULL && op==NULL) {
  445.     new_draw_info(NDI_UNIQUE, 0,op,"Inventory of what object?");
  446.     return;
  447.   }
  448.   tmp = inv ? inv->inv : op->inv;
  449.  
  450.   while (tmp) {
  451.     if ((!tmp->invisible && 
  452.         (inv==NULL || inv->type == CONTAINER || QUERY_FLAG(tmp, FLAG_APPLIED)))
  453.          || (!op || QUERY_FLAG(op, FLAG_WIZ)))
  454.       items++;
  455.     tmp=tmp->below;
  456.   }
  457.   if (inv==NULL) { /* player's inventory */
  458.     if (items==0) {
  459.       new_draw_info(NDI_UNIQUE, 0,op,"You carry nothing.");
  460.       return;
  461.     } else {
  462.       length = INFOCHARS-19;
  463.       in = "";
  464.       if (op)
  465.         clear_win_info(op);
  466.       new_draw_info(NDI_UNIQUE, 0,op,"Inventory:");
  467.     }
  468.   } else {
  469.     if (items==0) 
  470.       return;
  471.     else { 
  472.       length = INFOCHARS-21;
  473.       in = "  ";
  474.     }
  475.   }
  476.   for (tmp=inv?inv->inv:op->inv; tmp; tmp=tmp->below) {
  477.     if((!op||!QUERY_FLAG(op, FLAG_WIZ)) && (tmp->invisible || 
  478.        (inv && inv->type != CONTAINER && !QUERY_FLAG(tmp, FLAG_APPLIED))))
  479.       continue;
  480.     if((!op || QUERY_FLAG(op, FLAG_WIZ)))
  481.       (void) sprintf(buf,"%s- %-*s (%5d) %-8s", in, length, query_name(tmp),
  482.                      tmp->count,query_weight(tmp));
  483.     else
  484.       (void) sprintf(buf,"%s- %-*s %-8s", in, length+8, query_name(tmp),
  485.                      query_weight(tmp));
  486.     new_draw_info(NDI_UNIQUE, 0,op,buf);
  487.   }
  488.   if(!inv && op) {
  489.     sprintf(buf,"%-*s %-8s",
  490.             INFOCHARS-9,"Total weight carried:",query_weight(op));
  491.     new_draw_info(NDI_UNIQUE, 0,op,buf);
  492.   }
  493. }
  494.  
  495. /*
  496.  * look_at prints items on the specifc square.
  497.  * [ removed EARTHWALL check and added check for containers inventory.
  498.  *   Tero.Haatanen@lut.fi ]
  499.  */
  500. void look_at(object *op,int dx,int dy) {
  501.   object *tmp;
  502.   char buf[MAX_BUF];
  503.   int flag=0;
  504.  
  505.   if(op->above!=NULL) {
  506.     remove_ob(op);
  507.     insert_ob_in_map(op,op->map);
  508.   }
  509.   if(dx||dy) 
  510.     for(tmp=get_map_ob(op->map,op->x+dx,op->y+dy);tmp!=NULL&&tmp->above!=NULL;
  511.       tmp=tmp->above);
  512.   else
  513.     tmp=op->below;
  514.   while(tmp && (QUERY_FLAG(op, FLAG_WIZ) ||(!tmp->invisible && tmp!=op))) {
  515.     if(!flag) {
  516.       if(dx||dy)
  517.         new_draw_info(NDI_UNIQUE, 0,op,"There you see:");
  518.       else {
  519.         clear_win_info(op);
  520.         new_draw_info(NDI_UNIQUE, 0,op,"You see:");
  521.       }
  522.       flag=1;
  523.     }
  524.     if(QUERY_FLAG(op, FLAG_WIZ))
  525.       (void) sprintf(buf,"- %s (%d).",query_name(tmp),tmp->count);
  526.     else
  527.       (void) sprintf(buf,"- %s.",query_name(tmp));
  528.     new_draw_info(NDI_UNIQUE, 0,op,buf);
  529.     if((tmp->inv!=NULL || (tmp->head && tmp->head->inv)) && 
  530.        ( (!dx&&!dy) || tmp->type != CONTAINER || QUERY_FLAG(op, FLAG_WIZ)
  531. /* added some cases here -b.t. */
  532.     || !(tmp->type) || tmp->type!=FLESH ))
  533.       inventory(op,tmp->head==NULL?tmp:tmp->head);
  534.     if(QUERY_FLAG(tmp, FLAG_IS_FLOOR)&&!QUERY_FLAG(op, FLAG_WIZ))    /* don't continue under the floor */
  535.       break;
  536.     tmp=tmp->below;
  537.   }
  538.   if(!flag)
  539.     if(dx||dy)
  540.       new_draw_info(NDI_UNIQUE, 0,op,"You see nothing there.");
  541.     else
  542.       new_draw_info(NDI_UNIQUE, 0,op,"You see nothing.");
  543. }
  544.  
  545.  
  546.  
  547. void receive_player_name(object *op,char k) {
  548.   if(k!=13) {
  549.     if((k==8||k==127)&&(op->contr->writing==1))
  550.       return;
  551.     if(k!=8&&k!=127&&!((k>='a'&&k<='z')||(k>='A'&&k<='Z'))&&k!='-'&&k!='_')
  552.       return;
  553.     write_ch(op,k);
  554.     return;
  555.   }
  556.   if(op->contr->writing<=1) {
  557.     if (op->contr->eric_server>0) get_name(op);
  558.     return;
  559.   }
  560.   if(!check_name(op->contr,op->contr->write_buf+1)) {
  561.       get_name(op);
  562.       return;
  563.   }
  564.   if(op->name!=NULL)
  565.     free_string(op->name);
  566.   op->name=add_string(op->contr->write_buf+1);
  567.   new_draw_info(NDI_UNIQUE, 0,op,op->contr->write_buf);
  568.   op->contr->last_value= -1; /* Flag: redraw all stats */
  569.   draw_stats(op);
  570.   op->contr->name_changed=1;
  571.   get_password(op);
  572. }
  573.  
  574. void receive_player_password(object *op,char k) {
  575.   if(k!=13) {
  576.     if(k!=8&&k!=127&&(!((k>='a'&&k<='z')||(k>='A'&&k<='Z'))||
  577.        op->contr->writing>8)) /* Max 8 characters in password */
  578.       return;
  579.     write_ch(op,k);
  580.     return;
  581.   }
  582.   op->contr->no_echo=0;
  583.   if(op->contr->writing<=1) {
  584.     remove_lock(op->contr);
  585.     get_name(op);
  586.     return;
  587.   }
  588.   op->contr->writing=0;
  589.   new_draw_info(NDI_UNIQUE, 0,op,"          "); /* To hide the password better */
  590.   if(op->contr->state==ST_CONFIRM_PASSWORD) {
  591.     if(!check_password(op->contr->write_buf+1,op->contr->password)) {
  592.       new_draw_info(NDI_UNIQUE, 0,op,"The passwords did not match.");
  593.       remove_lock(op->contr);
  594.       get_name(op);
  595.       return;
  596.     }
  597.     clear_win_info(op);
  598.     display_motd(op);
  599.     new_draw_info(NDI_UNIQUE, 0,op," ");
  600.     new_draw_info(NDI_UNIQUE, 0,op,"Welcome, Brave New Warrior!");
  601.     new_draw_info(NDI_UNIQUE, 0,op," ");
  602.     Roll_Again(op);
  603.     op->contr->state=ST_ROLL_STAT;
  604.     return;
  605.   }
  606.   strcpy(op->contr->password,crypt_string(op->contr->write_buf+1,NULL));
  607.   op->contr->state=ST_ROLL_STAT;
  608.   check_login(op);
  609.   return;
  610. }
  611.  
  612.  
  613. void set_pickup_mode(object *op,int i) {
  614.   switch(op->contr->mode=i) {
  615.     case 0:
  616.       new_draw_info(NDI_UNIQUE, 0,op,"Mode: Don't pick up.");
  617.       break;
  618.     case 1:
  619.       new_draw_info(NDI_UNIQUE, 0,op,"Mode: Pick up one item.");
  620.       break;
  621.     case 2:
  622.       new_draw_info(NDI_UNIQUE, 0,op,"Mode: Pick up one item and stop.");
  623.       break;
  624.     case 3:
  625.       new_draw_info(NDI_UNIQUE, 0,op,"Mode: Stop before picking up.");
  626.       break;
  627.     case 4:
  628.       new_draw_info(NDI_UNIQUE, 0,op,"Mode: Pick up all items.");
  629.       break;
  630.     case 5:
  631.       new_draw_info(NDI_UNIQUE, 0,op,"Mode: Pick up all items and stop.");
  632.       break;
  633.     case 6:
  634.       new_draw_info(NDI_UNIQUE, 0,op,"Mode: Pick up all magic items.");
  635.       break;
  636.     case 7:
  637.       new_draw_info(NDI_UNIQUE, 0,op,"Mode: Pick up all coins and gems");
  638.       break;
  639.     }
  640. }
  641.  
  642. int explore_mode() {
  643. #ifdef EXPLORE_MODE
  644.   player *pl;
  645.   for (pl = first_player; pl != (player *) NULL; pl = pl->next)
  646.     if (pl->explore)
  647.       return 1;
  648. #endif
  649.   return 0;
  650. }
  651.  
  652. /*
  653.  * Actual commands.
  654.  * Those should be in small separate files (c_object.c, c_wiz.c, cmove.c,...)
  655.  */
  656.  
  657.  
  658. static void help_topics(object *op, int what)
  659. {
  660.   XDIR *dirp;
  661.   struct xdirect *de;
  662.   char filename[MAX_BUF], line[80];
  663.   int namelen, linelen=0;
  664.   
  665.   switch (what) {
  666.   case 1:
  667.     sprintf(filename, "%s/wizhelp", LibDir);
  668.     new_draw_info(NDI_UNIQUE, 0,op, "      Wiz commands:");
  669.     break;
  670.   case 2:
  671.     sprintf(filename, "%s/sockethelp", LibDir);
  672.     new_draw_info(NDI_UNIQUE, 0,op, "      Socket commands:");
  673.     break;
  674.   case 3:
  675.     sprintf(filename, "%s/mischelp", LibDir);
  676.     new_draw_info(NDI_UNIQUE, 0,op, "      Misc help:");
  677.     break;
  678.   default:
  679.     sprintf(filename, "%s/help", LibDir);
  680.     new_draw_info(NDI_UNIQUE, 0,op, "      Commands:");
  681.     break;
  682. }
  683.   if (!(dirp=xopendir(filename)))
  684.     return;
  685.   line[0] ='\0';
  686.   for (de = xreaddir(dirp, 1); de; de = xreaddir(dirp, 1)) {
  687.     namelen = de->d_namlen;
  688.     if (namelen <= 2 && *de->d_name == '.' &&
  689.     (namelen == 1 || de->d_name[1] == '.' ) )
  690.       continue;
  691.     linelen +=namelen+1;
  692.     if (linelen > 42) {
  693.       new_draw_info(NDI_UNIQUE, 0,op, line);
  694.       sprintf(line, " %s", de->d_name);
  695.       linelen =namelen+1;
  696.       continue;
  697.     }
  698.     strcat(line, " ");
  699.     strcat(line, de->d_name);
  700.   }           
  701.   new_draw_info(NDI_UNIQUE, 0,op, line);
  702.   xclosedir(dirp);
  703. }
  704.  
  705. static void show_commands(object *op, int what)
  706. {
  707.   char line[80];
  708.   int i, size, namelen, linelen=0;
  709.   CommArray_s *ap;
  710.   extern CommArray_s Commands[], WizCommands[], SocketCommands[];
  711.   extern const int CommandsSize, WizCommandsSize, SocketCommandsSize;
  712.   
  713.   switch (what) {
  714.   case 1:
  715.     ap =WizCommands;
  716.     size =WizCommandsSize;
  717.     new_draw_info(NDI_UNIQUE, 0,op, "      Wiz commands:");
  718.     break;
  719.   case 2:
  720.     ap =SocketCommands;
  721.     size = SocketCommandsSize;
  722.     new_draw_info(NDI_UNIQUE, 0,op, "      Socket commands:");
  723.     break;
  724.   default:
  725.     ap =Commands;
  726.     size =CommandsSize;
  727.     new_draw_info(NDI_UNIQUE, 0,op, "      Commands:");
  728.     break;
  729.   }
  730.  
  731.   line[0] ='\0';
  732.   for (i=0; i<size; i++) {
  733.     namelen = strlen(ap[i].name);
  734.     linelen +=namelen+1;
  735.     if (linelen > 42) {
  736.       new_draw_info(NDI_UNIQUE, 0,op, line);
  737.       sprintf(line, " %s", ap[i].name);
  738.       linelen =namelen+1;
  739.       continue;
  740.     }
  741.     strcat(line, " ");
  742.     strcat(line, ap[i].name);
  743.   }           
  744.   new_draw_info(NDI_UNIQUE, 0,op, line);
  745. }
  746.  
  747. int command_lock (object *op, char *params)
  748. {
  749.  
  750.   objectlink *list;
  751.  
  752.   list = id(op,op->inv,params,0);
  753.   if(!list) {
  754.     new_draw_info(NDI_UNIQUE, 0,op,"Nothing to lock!");
  755.     return 0;
  756.   }
  757.   op->contr->freeze_inv=1;
  758.   op->contr->freeze_look=1;
  759.   while(list) {
  760.     op->contr->count=list->id;
  761.     lock_inv(op,list->ob);
  762.     list=list->next;
  763.   }
  764.   op->contr->freeze_inv=0;
  765.   op->contr->count=0;
  766.   draw_inventory(op);
  767.   return 0;
  768. }
  769.  
  770. int command_unlock (object *op, char *params)
  771. {
  772.   objectlink *list;
  773.  
  774.   list = id(op,op->inv,params,0);
  775.   if(!list) {
  776.     new_draw_info(NDI_UNIQUE, 0,op,"Nothing to unlock!");
  777.     return 1;
  778.   }
  779.   op->contr->freeze_inv=1;
  780.   while(list) {
  781.     op->contr->count=list->id;
  782.     unlock_inv(op,list->ob);
  783.     list=list->next;
  784.   }
  785.   op->contr->freeze_inv=0;
  786.   op->contr->count=0;
  787.   draw_inventory(op);
  788.   return 0;
  789. }
  790.  
  791. int command_help (object *op, char *params)
  792. {
  793.   struct stat st;
  794.   FILE *fp;
  795.   char filename[MAX_BUF], line[MAX_BUF];
  796.   int len;
  797.  
  798.   if(op != NULL)
  799.     clear_win_info(op);
  800.  
  801. /*
  802.    * Main help page?
  803.  */
  804.   if (!params) {
  805.     sprintf(filename, "%s/def_help", LibDir);
  806.     if ((fp=fopen(filename, "r")) == NULL) {
  807.       LOG(llevError, "Can't open %s\n", filename);
  808.       perror("Can't read default help");
  809.       return 0;
  810.     }
  811.     while (fgets(line, MAX_BUF, fp)) {
  812.       line[MAX_BUF-1] ='\0';
  813.       len =strlen(line)-1;
  814.       if (line[len] == '\n')
  815.     line[len] ='\0';
  816.       new_draw_info(NDI_UNIQUE, 0,op, line);
  817.     }
  818.     fclose(fp);
  819.     return 0;
  820.   }
  821.  
  822.   /*
  823.    * Topics list
  824.    */
  825.   if (!strcmp(params, "topics")) {
  826.     help_topics(op, 3);
  827.     if (!op) {
  828.       help_topics(op, 2);
  829.       if (active_socket->wiz)
  830.     help_topics(op, 1);
  831.       return 0;
  832.     }
  833.     help_topics(op, 0);
  834.     if (QUERY_FLAG(op, FLAG_WIZ))
  835.       help_topics(op, 1);
  836.     return 0;
  837.     }
  838.   
  839.   /*
  840.    * Commands list
  841.    */
  842.   if (!strcmp(params, "commands")) {
  843.     if (!op) {
  844.       show_commands(op, 2);
  845.       if (active_socket->wiz)
  846.     show_commands(op, 1);
  847.       return 0;
  848.   }
  849.     show_commands(op, 0);
  850.     if (QUERY_FLAG(op, FLAG_WIZ))
  851.       show_commands(op, 1);
  852.     return 0;
  853.   }
  854.  
  855.   /*
  856.    * User wants info about command
  857.    */
  858.   if (strchr(params, '.') || strchr(params, ' ') || strchr(params, '/')) {
  859.     sprintf(line, "Illegal characters in '%s'", params);
  860.     new_draw_info(NDI_UNIQUE, 0,op, line);
  861.     return 0;
  862.   }
  863.  
  864.   sprintf(filename, "%s/mischelp/%s", LibDir, params);
  865.   if (stat(filename, &st) || !S_ISREG(st.st_mode)) {
  866.     if (op) {
  867.       sprintf(filename, "%s/help/%s", LibDir, params);
  868.       if (stat(filename, &st) || !S_ISREG(st.st_mode)) {
  869.     if (QUERY_FLAG(op, FLAG_WIZ)) {
  870.       sprintf(filename, "%s/wizhelp/%s", LibDir, params);
  871.       if (stat(filename, &st) || !S_ISREG(st.st_mode))
  872.         goto nohelp;
  873.     } else
  874.       goto nohelp;
  875.       }
  876.           } else {
  877.       sprintf(filename, "%s/sockethelp/%s", LibDir, params);
  878.       if (stat(filename, &st) || !S_ISREG(st.st_mode)) {
  879.     if (active_socket->wiz) {
  880.       sprintf(filename, "%s/wizhelp/%s", LibDir, params);
  881.       if (stat(filename, &st) || !S_ISREG(st.st_mode))
  882.         goto nohelp;
  883.     } else
  884.       goto nohelp;
  885.           }
  886.   }
  887.   }
  888.  
  889.   /*
  890.    * Found that. Just cat it to screen.
  891.    */
  892.   if ((fp=fopen(filename, "r")) == NULL) {
  893.     LOG(llevError, "Can't open %s\n", filename);
  894.     perror("Can't read helpfile");
  895.     return 0;
  896.       }
  897.   sprintf(line, "Help about '%s'", params);
  898.   new_draw_info(NDI_UNIQUE, 0,op, line);
  899.   while (fgets(line, MAX_BUF, fp)) {
  900.     line[MAX_BUF-1] ='\0';
  901.     len =strlen(line)-1;
  902.     if (line[len] == '\n')
  903.       line[len] ='\0';
  904.     new_draw_info(NDI_UNIQUE, 0,op, line);
  905.     }
  906.   fclose(fp);
  907.   return 0;
  908.  
  909.   /*
  910.    * No_help -escape
  911.    */
  912.  nohelp:
  913.   sprintf(line, "No help availble on '%s'", params);
  914.   new_draw_info(NDI_UNIQUE, 0,op, line);
  915.   return 0;
  916. }
  917.  
  918.  
  919. int command_chrfont (object *op, char *params)
  920. {
  921.   XFontStruct *tmp_font;
  922.   
  923.   if (params != NULL) {
  924.     if ((tmp_font=XLoadQueryFont(op->contr->gdisp, params)) != NULL) {
  925.       strcpy (op->contr->font_str, params);
  926.       XFreeFont(op->contr->gdisp, tmp_font);
  927.       } else {
  928.       LOG(llevError, "Crossfire: Couldn't load font %s.\n", params);
  929.       new_draw_info(NDI_UNIQUE, 0,op, "Couldn't load font.");
  930.       }
  931.   } else new_draw_info(NDI_UNIQUE, 0,op, "What font?");
  932.       return 1;
  933.     }
  934.  
  935.  
  936. int command_invoke(object *op, char *params)
  937. {
  938.     return command_cast_spell(op, params, 'i');
  939. }
  940.  
  941. int command_cast(object *op, char *params)
  942. {
  943.     return command_cast_spell(op, params, 'c');
  944. }
  945.  
  946. int command_prepare(object *op, char *params)
  947. {
  948.     return command_cast_spell(op, params, 'p');
  949. }
  950.  
  951. /* Some commands are not accepted from sockets */
  952.  
  953. int command_cast_spell (object *op, char *params, char command)
  954. {
  955.   int i, castnow=0;
  956.   char *cp=NULL;
  957.   char buf[MAX_BUF];
  958.  
  959.       if(!op->contr->nrofknownspells&&!QUERY_FLAG(op, FLAG_WIZ)) {
  960.         new_draw_info(NDI_UNIQUE, 0,op,"You don't know any spells.");
  961.         return 1;
  962.       }
  963.  
  964.       if(op->contr->golem!=NULL) {
  965.         remove_friendly_object(op->contr->golem);
  966.         remove_ob(op->contr->golem);
  967.         free_object(op->contr->golem);
  968.         op->contr->golem=NULL;
  969.       }
  970.  
  971.   if (command=='i') castnow = 1;
  972.   if(params!=NULL) {
  973.     int numknown; /* number of spells known by op */
  974.     int spnum;  /* number of spell that is being cast */
  975.  
  976.     /* rune of fire, rune of ... are special cases */
  977.     if (strncmp(params,"rune",4)) {
  978.     cp =strstr(params, " of ");
  979.         if (cp) {
  980.           *cp='\0';
  981.           cp +=4;
  982.     }
  983.     }
  984.  
  985.     if(QUERY_FLAG(op, FLAG_WIZ))
  986.     numknown = NROFREALSPELLS;
  987.     else 
  988.     numknown = op->contr->nrofknownspells;
  989.  
  990.     for(i=0;i<numknown;i++){
  991.         if (QUERY_FLAG(op, FLAG_WIZ)) spnum = i;
  992.         else spnum = op->contr->known_spells[i];
  993.  
  994.         if (!strncmp(params, spells[spnum].name, strlen(params))) {
  995.             rangetype orig_rangetype=op->contr->shoottype;
  996.             op->contr->shoottype=range_magic;
  997. #ifdef ALLOW_SKILLS 
  998.                     if(op->type==PLAYER&&!QUERY_FLAG(op,FLAG_WIZ)) { 
  999.                                  if(!check_skill_to_fire(op)) {  
  1000.                                      op->contr->shoottype=orig_rangetype;
  1001.                     return 0; 
  1002.                  }
  1003.                     } 
  1004. #endif
  1005.             if (castnow) { 
  1006.             int value;
  1007.  
  1008.                         /* Need to switch shoottype to range_magic - otherwise 
  1009.                          * cast_spell doesn't check to see if the character 
  1010.                          * has enough spellpoints. 
  1011.              * Note: now done above this -b.t. */
  1012.             /* op->contr->shoottype=range_magic; */ 
  1013.  
  1014.             value = cast_spell(op,op,op->facing,spnum,0,spellNormal,cp);
  1015.             op->contr->shoottype=orig_rangetype;
  1016.  
  1017.             if(spells[spnum].cleric) 
  1018.                 op->stats.grace -= value;
  1019.             else 
  1020.                 op->stats.sp -= value;
  1021.                       } else 
  1022.                         op->contr->chosen_spell=spnum;
  1023.  
  1024.             draw_stats(op);
  1025.             return 1;
  1026. /*
  1027.         op->stats.sp -= invoke_spell(op, op->facing, spnum, 0, spellNormal, cp);
  1028.         draw_stats(op);
  1029.         return 1;
  1030. */
  1031.         }
  1032.     }
  1033.   }
  1034.       new_draw_info(NDI_UNIQUE, 0,op,"Cast what spell?  Choose one of:");
  1035.  
  1036.       new_draw_info(NDI_UNIQUE, 0,op,"[sp] spell name");
  1037.       if(QUERY_FLAG(op, FLAG_WIZ))
  1038.         for(i=0;i<NROFREALSPELLS;i++)
  1039.       {
  1040. #ifdef SPELLPOINT_LEVEL_DEPEND
  1041.         sprintf(buf,"[%02d] %s",SP_level_spellpoint_cost(op,i),
  1042. #else
  1043.         sprintf(buf,"[%02d] %s",spells[i].sp,
  1044. #endif
  1045.             spells[i].name);
  1046.         new_draw_info(NDI_UNIQUE, 0,op,buf);
  1047.       }
  1048.       else
  1049.         for(i=0;i<(int)op->contr->nrofknownspells;i++)
  1050.       {
  1051. #ifdef SPELLPOINT_LEVEL_DEPEND
  1052.         sprintf(buf,"[%02d] %s",
  1053.         SP_level_spellpoint_cost(op,op->contr->known_spells[i]),
  1054. #else
  1055.         sprintf(buf,"[%02d] %s",spells[op->contr->known_spells[i]].sp,
  1056. #endif
  1057.             spells[op->contr->known_spells[i]].name);
  1058.         new_draw_info(NDI_UNIQUE, 0,op,buf);
  1059.       }
  1060.         return 1;
  1061. }
  1062.  
  1063. #ifdef SET_TITLE
  1064. int command_title (object *op, char *params)
  1065. {
  1066.       char buf[MAX_BUF];
  1067.   if(params == NULL) {
  1068.     if(op->contr->own_title[0]=='\0')
  1069.       sprintf(buf,"Your title is '%s'.",
  1070.           op->contr->title);
  1071.     else
  1072.       sprintf(buf,"Your title is '%s'.",
  1073.           op->contr->own_title);
  1074.     new_draw_info(NDI_UNIQUE, 0,op,buf);
  1075.     return 1;
  1076.       }
  1077.   if(strcmp(params, "clear")==0 || strcmp(params, "default")==0) {
  1078.     if(op->contr->own_title[0]=='\0')
  1079.       new_draw_info(NDI_UNIQUE, 0,op,"Your title is the default title.");
  1080.     else
  1081.       new_draw_info(NDI_UNIQUE, 0,op,"Title set to default.");
  1082.     op->contr->own_title[0]='\0';
  1083.     redraw_title(op);
  1084.     return 1;
  1085.       }
  1086.   if((int)strlen(params) >= MAX_NAME) {
  1087.     new_draw_info(NDI_UNIQUE, 0,op,"Title too long.");
  1088.     return 1;
  1089.       }
  1090.   strcpy(op->contr->own_title, params);
  1091.       redraw_title(op);
  1092.       return 1;
  1093.     }
  1094. #endif /* SET_TITLE */
  1095.  
  1096. int command_save (object *op, char *params)
  1097. {
  1098.       if(save_player(op,1))
  1099.     new_draw_info(NDI_UNIQUE, 0,op,"You have been saved.");
  1100.       else
  1101.     new_draw_info(NDI_UNIQUE, 0,op,"SAVE FAILED!");
  1102.       return 1;
  1103. }
  1104.  
  1105. #ifdef SEARCH_ITEMS
  1106. int command_search_items (object *op, char *params)
  1107. {
  1108.       char buf[MAX_BUF];
  1109.   if(params == NULL) {
  1110.     if(op->contr->search_str[0]=='\0') {
  1111.       new_draw_info(NDI_UNIQUE, 0,op,"Example: search magic+1");
  1112.       new_draw_info(NDI_UNIQUE, 0,op,"Would automatically pick up all");
  1113.       new_draw_info(NDI_UNIQUE, 0,op,"items containing the word 'magic+1'.");
  1114.       return 1;
  1115.     }
  1116.     op->contr->search_str[0]='\0';
  1117.     new_draw_info(NDI_UNIQUE, 0,op,"Search mode turned off.");
  1118.     fix_player(op);
  1119.     draw_stats(op);
  1120.     return 1;
  1121.       }
  1122.   if((int)strlen(params) >= MAX_BUF) {
  1123.     new_draw_info(NDI_UNIQUE, 0,op,"Search string too long.");
  1124.     return 1;
  1125.       }
  1126.   strcpy(op->contr->search_str, params);
  1127.       sprintf(buf,"Searching for '%s'.",op->contr->search_str);
  1128.       new_draw_info(NDI_UNIQUE, 0,op,buf);
  1129.   fix_player(op);
  1130.   draw_stats(op);
  1131.       return 1;
  1132.     }
  1133. #endif /* SEARCH_ITEMS */
  1134.  
  1135. int command_peaceful (object *op, char *params)
  1136. {
  1137.       if((op->contr->peaceful=!op->contr->peaceful))
  1138.         new_draw_info(NDI_UNIQUE, 0,op,"You will not attack other players.");
  1139.       else
  1140.         new_draw_info(NDI_UNIQUE, 0,op,"You will attack other players.");
  1141.       return 1;
  1142.     }
  1143.  
  1144. int command_scroll (object *op, char *params)
  1145. {
  1146.       if((op->contr->scroll=!op->contr->scroll)) {
  1147.     new_draw_info(NDI_UNIQUE, 0,op,"Scroll is enabled.");
  1148.     if (op->contr->infofull) {
  1149.         op->contr->infoline = op->contr->infolines - 1;
  1150.         draw_all_info(op);
  1151.     }
  1152.       }
  1153.       else {
  1154.     /* simply put, in scroll mode, infopos does not have to be equal
  1155.      * to infoline.  However, infopos must equal infoline in wrap
  1156.      * mode.  A simple infopos=infoline solves this, but if a redraw
  1157.      * was needed, the redraw wouldn't look right, so we copy the
  1158.      * info array to make things right.
  1159.      * Mark Wedel (master@cats.ucsc.edu)
  1160.      */
  1161.     int i;
  1162.     char    **info;
  1163.     if ((op->contr->infofull) &&
  1164.        (op->contr->infoline != op->contr->infopos)){
  1165.         info = (char **) malloc(sizeof(char *) * op->contr->infolines);
  1166.       for (i=0; i<(int)op->contr->infolines; i++) {
  1167.             info[i] = malloc(sizeof(char) * (op->contr->infochars+1));
  1168.     strncpy(info[i], op->contr->info[(i+op->contr->infopos) % (int)op->contr->infolines],op->contr->infochars);
  1169.             info[i][op->contr->infochars] = '\0';
  1170.         }
  1171.       for (i=0; i<(int)op->contr->infolines; i++)
  1172.             free(op->contr->info[i]);
  1173.         free(op->contr->info);
  1174.         op->contr->info = info;
  1175.         op->contr->infopos = op->contr->infoline;
  1176.         draw_all_info(op);
  1177.     }
  1178.         new_draw_info(NDI_UNIQUE, 0,op,"Scroll is disabled.");
  1179.       }
  1180.       return 1;
  1181.     }
  1182.  
  1183. int command_berzerk (object *op, char *params)
  1184. {
  1185.       if((op->contr->berzerk=!op->contr->berzerk))
  1186.         new_draw_info(NDI_UNIQUE, 0,op,"Berzerk is enabled.");
  1187.       else
  1188.         new_draw_info(NDI_UNIQUE, 0,op,"Berzerk is disabled.");
  1189.       return 1;
  1190.     }
  1191.  
  1192. int command_strength (object *op, char *params)
  1193. {
  1194.       int i;
  1195.   if(params==NULL || !sscanf(params, "%d", &i) ||
  1196.          (!QUERY_FLAG(op, FLAG_WIZ)&&(i<5||i>op->stats.maxsp))) {
  1197.         new_draw_info(NDI_UNIQUE, 0,op,"Set which strength?");
  1198.         return 1;
  1199.       }
  1200.       op->contr->shootstrength=i;
  1201.       new_draw_info(NDI_UNIQUE, 0,op,"OK.");
  1202.       return 1;
  1203.     }
  1204.  
  1205. int command_pickup (object *op, char *params)
  1206. {
  1207.       int i;
  1208.  
  1209.   if(!params) {
  1210.     op->contr->count_left=0;
  1211.     set_pickup_mode(op, (op->contr->mode > 6)? 0: op->contr->mode+1);
  1212.     return 0;
  1213.   }
  1214.   if(params==NULL || !sscanf(params, "%d", &i) || i<0 ) {
  1215.         new_draw_info(NDI_UNIQUE, 0,op,"Usage: pickup <0-7> or <value_density> .");
  1216.         return 1;
  1217.       }
  1218.       set_pickup_mode(op,i);
  1219.       return 1;
  1220. }
  1221.  
  1222. int command_protocol (object *op, char *params)
  1223. {
  1224.   int i;
  1225.   if (params == NULL || !sscanf(params, "%d", &i)) {
  1226.       new_draw_info(NDI_UNIQUE, 0,op,"Set what protocol?");
  1227.       return 1;
  1228.   }
  1229.   set_protocol(active_socket, i);
  1230.   return 1;
  1231. }
  1232.  
  1233. int command_set (object *op, char *params)
  1234. {
  1235.   if (params == NULL) {
  1236.     /* Lets tell what options are available */
  1237.     new_draw_info(NDI_UNIQUE, 0,op, "Options you can set are:");
  1238.     new_draw_info(NDI_UNIQUE, 0,op, "font:    Use normal font mode");
  1239.     new_draw_info(NDI_UNIQUE, 0,op, "pixmaps: Use pixmaps instead of font");
  1240.     new_draw_info(NDI_UNIQUE, 0,op, "split:   Start in split window mode");
  1241. #ifdef Xpm_Pix
  1242.     new_draw_info(NDI_UNIQUE, 0,op, "xpm: Use X Pixmaps for display");
  1243. #endif
  1244.         return 1;
  1245.       }
  1246.  
  1247.       /* Lets not be picky about case */
  1248.  
  1249.   if(!strcasecmp(params, "font")) {
  1250.         active_socket->use_pix = 0;
  1251.     active_socket->color_pix = 0;
  1252.         new_draw_info(NDI_UNIQUE, 0,op, "OK.");
  1253.         return 1;
  1254.       }
  1255.   if(!strcasecmp(params, "pixmaps")) {
  1256.         active_socket->use_pix = 1;
  1257.     active_socket->color_pix = 0;
  1258.         new_draw_info(NDI_UNIQUE, 0,op, "OK.");
  1259.         return 1;
  1260.       }
  1261.   if(!strcasecmp(params, "split")) {
  1262.         active_socket->split = 1;
  1263.         new_draw_info(NDI_UNIQUE, 0,op, "OK.");
  1264.         return 1;
  1265.       }
  1266. #ifdef Xpm_Pix
  1267.   if (!strcasecmp(params, "xpm")) {
  1268.     active_socket->color_pix = 1;
  1269.         active_socket->use_pix = 0;
  1270.     new_draw_info(NDI_UNIQUE, 0,op, "OK.");
  1271.     return 1;
  1272.       }
  1273. #endif
  1274.       new_draw_info(NDI_UNIQUE, 0,op,"Unknown option.\n");
  1275.       return 1;
  1276.     }
  1277.  
  1278. int command_unset (object *op, char *params)
  1279. {
  1280.   if (params == NULL) {
  1281.         new_draw_info(NDI_UNIQUE, 0,op, "Unset what option?");
  1282.         return 1;
  1283.       }
  1284.   if(!strcmp(params,"pixmaps")) {
  1285.         active_socket->use_pix = 0;
  1286.         new_draw_info(NDI_UNIQUE, 0,op, "OK.");
  1287.         return 1;
  1288.       }
  1289.   if(!strcmp(params,"split")) {
  1290.         active_socket->split = 0;
  1291.         new_draw_info(NDI_UNIQUE, 0,op, "OK.");
  1292.         return 1;
  1293.       }
  1294. #ifdef Xpm_Pix
  1295.   if (!strcasecmp(params,"xpm")) {
  1296.     active_socket->color_pix = 0;
  1297.     new_draw_info(NDI_UNIQUE, 0,op, "OK.");
  1298.     return 1;
  1299.       }
  1300. #endif
  1301.       new_draw_info(NDI_UNIQUE, 0,op,"Unknown option.\n");
  1302.       return 1;
  1303.     }
  1304.  
  1305. /*
  1306.  * Now follows non-dm-commands which are also acceptable from sockets
  1307.  */
  1308.  
  1309. int command_sync (object *op, char *params)
  1310. {
  1311.     int i;
  1312.     char buf[MAX_BUF];
  1313.   if (params==NULL || !sscanf(params, "%d", &i)) {
  1314.       sprintf(buf, "Your current sync is %d.",
  1315. #ifdef SERVER
  1316.         op ? op->contr->sync : active_socket->sync
  1317. #else
  1318.         op->contr->sync
  1319. #endif
  1320.         );
  1321.       new_draw_info(NDI_UNIQUE, 0,op, buf);
  1322.     }
  1323. #ifdef SERVER
  1324.     if (!op)
  1325.       active_socket->sync = i;
  1326.     else
  1327. #endif
  1328.       op->contr->sync = i;
  1329.     new_draw_info(NDI_UNIQUE, 0,op,"OK.");
  1330.     return 1;
  1331.   }
  1332.  
  1333. int command_name (object *op, char *params)
  1334. {
  1335.   if(params == NULL) {
  1336.       new_draw_info(NDI_UNIQUE, 0,op,"Change name to what?");
  1337.       return 1;
  1338.     }
  1339.     if(op == NULL) {
  1340.     strncpy(active_socket->name, params, 8);
  1341.       active_socket->name[8]='\0';
  1342.       new_draw_info(NDI_UNIQUE, 0,NULL,"OK.");
  1343.       return 1;
  1344.     }
  1345.     new_draw_info(NDI_UNIQUE, 0,op,"You can't change your name.");
  1346.     return 1;
  1347.   }
  1348.  
  1349.  
  1350. int command_wimpy (object *op, char *params)
  1351. {
  1352.     int i;
  1353.   char buf[MAX_BUF];
  1354.  
  1355.   if (params==NULL || !sscanf(params, "%d", &i)) {
  1356.       sprintf(buf, "Your current wimpy level is %d.", op->run_away);
  1357.       new_draw_info(NDI_UNIQUE, 0,op, buf);
  1358.       return 1;
  1359.     }
  1360.     sprintf(buf, "Your new wimpy level is %d.", i);
  1361.     new_draw_info(NDI_UNIQUE, 0,op, buf);
  1362.     op->run_away = i;
  1363.     return 1;
  1364.   }
  1365.  
  1366. int command_quit (object *op, char *params)
  1367. {
  1368.     if(op == NULL) {
  1369.       new_draw_info(NDI_UNIQUE, 0,NULL,"Goodbye.");
  1370.       active_socket->quit = 1;
  1371.       return 1;
  1372.     }
  1373.     if(op->stats.exp&&!QUERY_FLAG(op, FLAG_WAS_WIZ)) {
  1374.       new_draw_info(NDI_UNIQUE, 0,op,"This will delete your character!");
  1375.       new_draw_info(NDI_UNIQUE, 0,op,"Are you still sure you want to quit(y/n)?");
  1376.     } else
  1377.       new_draw_info(NDI_UNIQUE, 0,op,"Are you sure you want to quit(y/n)?");
  1378.  
  1379.     if (op->contr->eric_server>0)
  1380.     send_query(op->contr->eric_server,CS_QUERY_SINGLECHAR,"");
  1381.  
  1382.     op->contr->state = ST_CONFIRM_QUIT;
  1383.     return 1;
  1384.   }
  1385.  
  1386. #ifdef EXPLORE_MODE
  1387. /*
  1388.  * don't allow people to exit explore mode.  It otherwise becomes
  1389.  * really easy to abuse this.
  1390.  */
  1391. int command_explore (object *op, char *params)
  1392. {
  1393.   /*
  1394.    * I guess this is the best way to see if we are solo or not.  Actually,
  1395.    * are there any cases when first_player->next==NULL and we are not solo?
  1396.    */
  1397.       if ((first_player!=op->contr) || (first_player->next!=NULL)) {
  1398.       new_draw_info(NDI_UNIQUE, 0,op,"You can not enter explore mode if you are in a party");
  1399.       }
  1400.       else if (op->contr->explore)
  1401.               new_draw_info(NDI_UNIQUE, 0,op, "There is no return from explore mode");
  1402.       else {
  1403.         op->contr->explore=1;
  1404.         new_draw_info(NDI_UNIQUE, 0,op, "You are now in explore mode");
  1405.       }
  1406.       return 1;
  1407.     }
  1408. #endif
  1409.  
  1410. #ifdef SOUND_EFFECTS
  1411. int command_sound (object *op, char *params)
  1412. {
  1413.     if ((op->contr->rplay_fd = - op->contr->rplay_fd) > 0)
  1414.       new_draw_info(NDI_UNIQUE, 0,op, "The sounds are enabled.");
  1415.     else
  1416.       new_draw_info(NDI_UNIQUE, 0,op, "Silence is golden...");
  1417.     return 1;
  1418.   }
  1419. #endif
  1420.  
  1421. int command_add (object *op, char *params)
  1422. {
  1423.     int i, pixtmp = use_pixmaps, cpix = color_pix;
  1424.     long splittmp = default_split_window;
  1425.     int synctmp = synchronize;
  1426.     char username[9];
  1427. #ifdef EXPLORE_MODE
  1428.     if (explore_mode()) {
  1429.     new_draw_info(NDI_UNIQUE, 0,op,"You are not able to add new players in explore mode.");
  1430.     return 1;
  1431.     }
  1432. #endif
  1433. #ifdef NO_ADD
  1434.     if(op != NULL) {
  1435.       new_draw_info(NDI_UNIQUE, 0,op, "Add is disabled.  Use the client.");
  1436.       return 1;
  1437.     }
  1438. #endif
  1439.   if(params == NULL) {
  1440.       if(op != NULL)
  1441.         op->contr->writing=0;
  1442.       new_draw_info(NDI_UNIQUE, 0,op,"Add which display?");
  1443.       return 1;
  1444.     }
  1445.     if (active_socket != (sockets *) NULL)
  1446.     {
  1447.       color_pix = active_socket->color_pix;
  1448.       use_pixmaps = (int) active_socket->use_pix;
  1449.       default_split_window = (long) active_socket->split;
  1450.       synchronize = active_socket->sync;
  1451.       strcpy(username, active_socket->name);
  1452.     }
  1453.     else
  1454.       *username = '\0';
  1455.     i=add_player(params, *username ? username : NULL, NULL,0);
  1456.     use_pixmaps = pixtmp;
  1457.     default_split_window = splittmp;
  1458.     synchronize = synctmp;
  1459.     color_pix = cpix;
  1460.     /* This player can be freed during a add_player() */
  1461.     if(op == NULL || (op->type == PLAYER && !QUERY_FLAG(op,FLAG_FREED)))
  1462.       new_draw_info(NDI_UNIQUE, 0,op, (i ? errmsg : "OK."));
  1463.     return 1;
  1464.   }
  1465.  
  1466. int command_shout (object *op, char *params)
  1467. {
  1468.     char buf[MAX_BUF];
  1469.   if (params == NULL) {
  1470.       new_draw_info(NDI_UNIQUE, 0,op,"Shout what?");
  1471.       return 1;
  1472.     }
  1473.     if (op == NULL) {
  1474.       strcpy(buf,active_socket->name);
  1475.       strcat(buf," shouts: ");
  1476.     } else {
  1477.       strcpy(buf,op->name);
  1478.       strcat(buf," shouts: ");
  1479.     }
  1480.   strncat(buf, params, MAX_BUF-30);
  1481.     buf[MAX_BUF - 1] = '\0';
  1482.     new_draw_info(NDI_UNIQUE | NDI_ALL | NDI_RED, 1, NULL, buf);
  1483.     return 1;
  1484.   }
  1485.  
  1486. int command_tell (object *op, char *params)
  1487. {
  1488.     char buf[MAX_BUF],*name = NULL ,*msg = NULL;
  1489.     player *pl;
  1490. #ifdef SERVER
  1491.     sockets *s;
  1492. #endif /* SERVER */
  1493.     if ( params != NULL){
  1494.         name = params;
  1495.         msg = strchr(name, ' ');
  1496.         if(msg){
  1497.          *(msg++)=0;
  1498.          if(*msg == 0)
  1499.         msg = NULL;
  1500.         }
  1501.     }
  1502.  
  1503.     if( name == NULL ){
  1504.     new_draw_info(NDI_UNIQUE, 0,op,"Tell whom what?");
  1505.     return 1;
  1506.     } else if ( msg == NULL){
  1507.     sprintf(buf, "Tell %s what?", name);
  1508.     new_draw_info(NDI_UNIQUE, 0,op,buf);
  1509.     return 1;
  1510.     }
  1511.  
  1512.  
  1513.     if (op == NULL)
  1514.       sprintf(buf,"%s tells you: %s",active_socket->name,msg);
  1515.     else
  1516.       sprintf(buf,"%s tells you: %s",op->name,msg);
  1517.     for(pl=first_player;pl!=NULL;pl=pl->next)
  1518.       if(strncasecmp(pl->ob->name,name,MAX_NAME)==0)
  1519.       {
  1520.     new_draw_info(NDI_UNIQUE | NDI_WHITE, 0, pl->ob, buf);
  1521.         return 1;
  1522.       }
  1523. #ifdef SERVER
  1524.     for(s = first_socket; s != (sockets *) NULL; s = s->next)
  1525.       if(strncasecmp(s->name,name,MAX_NAME)==0)
  1526.       {
  1527.         draw_socket(s->fd,buf);
  1528.         return 1;
  1529.       }
  1530.     new_draw_info(NDI_UNIQUE, 0,op,"No such player or socket.");
  1531. #else
  1532.     new_draw_info(NDI_UNIQUE, 0,op,"No suck player.");
  1533. #endif /* SERVER */
  1534.     return 1;
  1535.   }
  1536.  
  1537. int command_bell (object *op, char *params)
  1538. {
  1539.     char buf[MAX_BUF];
  1540.     player *pl;
  1541. #ifdef SERVER
  1542.     sockets *s;
  1543. #endif /* SERVER */
  1544.   if (params == NULL) {
  1545.       new_draw_info(NDI_UNIQUE, 0,op,"Bell whom?");
  1546.       return 1;
  1547.     }
  1548.     for(pl=first_player;pl!=NULL;pl=pl->next)
  1549.     if(strncasecmp(pl->ob->name, params, MAX_NAME)==0)
  1550.       {
  1551.         if (op == NULL)
  1552.           sprintf(buf,"%s bells you.",active_socket->name);
  1553.         else
  1554.           sprintf(buf,"%s bells you.",op->name);
  1555.         new_draw_info(NDI_UNIQUE, 0,pl->ob,buf);
  1556.         XBell(pl->ob->contr->gdisp,100);
  1557.         return 1;
  1558.       }
  1559. #ifdef SERVER
  1560.     for(s = first_socket; s != (sockets *) NULL; s = s->next)
  1561.     if(strncasecmp(s->name, params, MAX_NAME)==0)
  1562.       {
  1563.         if (op == NULL)
  1564.           sprintf(buf,"%s bells you.%c",active_socket->name,7);
  1565.         else
  1566.           sprintf(buf,"%s bells you.%c",op->name,7);
  1567.         draw_socket(s->fd,buf);
  1568.         return 1;
  1569.       }
  1570. #endif /* SERVER */
  1571.   return 0;
  1572.   }
  1573.  
  1574. /**************************************************************************/
  1575.  
  1576. /* Returns TRUE if the range specified (int r) is legal - that is,
  1577.  * the character has an item that is equipped for that range type.
  1578.  * return 0 if there is no item of that range type that is usable.
  1579.  */
  1580.  
  1581. int legal_range(object *op,int r) {
  1582.   int i;
  1583.   object *tmp;
  1584.  
  1585.   switch(r) {
  1586.   case range_none: /* "Nothing" is always legal */
  1587.     return 1;
  1588.   case range_bow: /* bows */
  1589.     for (tmp=op->inv; tmp!=NULL; tmp=tmp->below)
  1590.       if (tmp->type == BOW && QUERY_FLAG(tmp, FLAG_APPLIED))
  1591.     return 1;
  1592.     return 0;
  1593.   case range_magic: /* cast spells */
  1594.     if (op->contr->nrofknownspells == 0)
  1595.       return 0;
  1596.     for (i = 0; i < op->contr->nrofknownspells; i++)
  1597.       if (op->contr->known_spells[i] == op->contr->chosen_spell)
  1598.         return 1;
  1599.     op->contr->chosen_spell = op->contr->known_spells[0];
  1600.     return 1;
  1601.   case range_wand: /* use wands */
  1602.     for (tmp=op->inv; tmp!=NULL; tmp=tmp->below)
  1603.       if (tmp->type == WAND && QUERY_FLAG(tmp, FLAG_APPLIED)) {
  1604.         if (QUERY_FLAG(tmp, FLAG_BEEN_APPLIED) || QUERY_FLAG(tmp, FLAG_IDENTIFIED))
  1605.           op->contr->known_spell = 1;
  1606.         else
  1607.           op->contr->known_spell = 0;
  1608.         op->contr->chosen_item_spell=tmp->stats.sp;
  1609.         return 1;
  1610.       }
  1611.     return 0;
  1612.   case range_rod:
  1613.     for (tmp=op->inv; tmp!=NULL; tmp=tmp->below)
  1614.       if (tmp->type == ROD && QUERY_FLAG(tmp, FLAG_APPLIED)) {
  1615.         if (QUERY_FLAG(tmp,FLAG_BEEN_APPLIED) || QUERY_FLAG(tmp, FLAG_IDENTIFIED))
  1616.           op->contr->known_spell = 1;
  1617.         else
  1618.           op->contr->known_spell = 0;
  1619.         op->contr->chosen_item_spell=tmp->stats.sp;
  1620.         return 1;
  1621.       }
  1622.     return 0;
  1623.   case range_horn:
  1624.     for (tmp=op->inv; tmp!=NULL; tmp=tmp->below)
  1625.       if (tmp->type == HORN && QUERY_FLAG(tmp, FLAG_APPLIED)) {
  1626.         if (QUERY_FLAG(tmp,FLAG_BEEN_APPLIED) || QUERY_FLAG(tmp, FLAG_IDENTIFIED))
  1627.           op->contr->known_spell = 1;
  1628.         else
  1629.           op->contr->known_spell = 0;
  1630.         op->contr->chosen_item_spell=tmp->stats.sp;
  1631.         return 1;
  1632.       }
  1633.     return 0;
  1634.   case range_scroll: /* Use scrolls */
  1635.     return 0;
  1636.   case range_skill:
  1637.       for (tmp = op->inv; tmp!=NULL; tmp=tmp->below) {
  1638.       if (tmp->type == SKILL) { 
  1639.           return 1;
  1640.       }
  1641.       }
  1642.       op->chosen_skill=NULL;    /* they have lost all skills :) */ 
  1643.       return 0;
  1644.   }
  1645.   return 0;
  1646. }
  1647.  
  1648. void change_spell(object *op,char k) {
  1649.   char buf[MAX_BUF];
  1650.   if(op->contr->golem!=NULL) {
  1651.     remove_friendly_object(op->contr->golem);
  1652.     remove_ob(op->contr->golem);
  1653.     free_object(op->contr->golem);
  1654.     op->contr->golem=NULL;
  1655.   }
  1656.   do {
  1657.     op->contr->shoottype += ((k == '+') ? 1 : -1);
  1658.     if(op->contr->shoottype >= range_size)
  1659.       op->contr->shoottype = range_none;
  1660.     else if (op->contr->shoottype <= range_bottom)
  1661.       op->contr->shoottype = (rangetype) range_size-1;
  1662.   } while (!legal_range(op,op->contr->shoottype));
  1663.   switch(op->contr->shoottype) {
  1664.   case range_none:
  1665.     strcpy(buf,"No ranged attack chosen.");
  1666.     break;
  1667.   case range_bow: {
  1668.     object *tmp;
  1669.     for (tmp = op->inv; tmp; tmp = tmp->below)
  1670.       if (tmp->type == BOW && QUERY_FLAG (tmp, FLAG_APPLIED))
  1671.         break;
  1672.     sprintf (buf, "Switched to %s and %s.", query_name(tmp),
  1673.          tmp && tmp->race ? tmp->race : "nothing");
  1674.     }
  1675.     break;
  1676.   case range_magic:
  1677.     sprintf(buf,"Switched to spells (%s).",
  1678.             spells[op->contr->chosen_spell].name);
  1679.     new_draw_info(NDI_UNIQUE, 0,op,buf);
  1680.     break;
  1681.   case range_wand:
  1682.     sprintf(buf,"Switched to wand (%s).",
  1683.             op->contr->known_spell ?
  1684.               spells[op->contr->chosen_item_spell].name : "unknown");
  1685.     break;
  1686.   case range_rod:
  1687.     sprintf(buf, "Switched to rod (%s).",
  1688.             op->contr->known_spell ?
  1689.             spells[op->contr->chosen_item_spell].name : "unknown");
  1690.     break;
  1691.   case range_horn:
  1692.     sprintf(buf, "Switched to horn (%s).",
  1693.             op->contr->known_spell ?
  1694.             spells[op->contr->chosen_item_spell].name : "unknown");
  1695.     break;
  1696.   case range_skill: 
  1697.     sprintf (buf, "Switched to skill: %s", op->chosen_skill ?  
  1698.          op->chosen_skill->name : "none");
  1699.     break;
  1700.   default:
  1701.     break;
  1702.   }
  1703.   new_draw_info(NDI_UNIQUE, 0,op,buf);
  1704.   draw_stats(op);
  1705. }
  1706.  
  1707. #ifdef SAVE_WINDOW_POSITIONS
  1708. void get_window_coord(object *op, Window win,
  1709.          int *x,int *y,
  1710.          int *wx,int *wy,
  1711.          unsigned int *w,unsigned int *h)
  1712. {
  1713.   Window root,child;
  1714.   unsigned int tmp;
  1715.   XGetGeometry(op->contr->gdisp,win,
  1716.            &root,
  1717.            x,y,w,h,
  1718.            &tmp,&tmp);
  1719.   XTranslateCoordinates(op->contr->gdisp,win,root,
  1720.             0,0,wx,wy,
  1721.             &child);
  1722. }
  1723. #endif /* SAVE_WINDOW_POSITIONS */
  1724.  
  1725. int command_rotateinventory (object *op, char *params)
  1726. {
  1727.   int size, i, j=1;
  1728.   object *head, *tail, *tmp;
  1729.   char buf[MAX_BUF];
  1730.  
  1731.   if (params && params[0])
  1732.     sscanf(params, "%d", &j);
  1733.  
  1734.   if (!j)
  1735.     return 0;
  1736.   if(!op->inv) {
  1737.     new_draw_info(NDI_UNIQUE, 0,op,"You don't carry anything.");
  1738.     return 0;
  1739.   }
  1740.  
  1741.   for (size=0,tmp=op->inv; tmp; tmp=tmp->below)
  1742.     if (!tmp->invisible)
  1743.       size++;
  1744.   if (size < 2) {
  1745.     new_draw_info(NDI_UNIQUE, 0,op,"You only carry one thing.");
  1746.     return 0;
  1747.   }
  1748.   if (FABS(j) >= size) {
  1749.     new_draw_info(NDI_UNIQUE, 0,op, "Value too big");
  1750.     return 0;
  1751.   }
  1752.  
  1753.   op->contr->last_used =NULL;
  1754.   op->contr->last_used_id =0;
  1755.  
  1756.   if (j<0) {
  1757.     for (i=0,head=NULL,tmp=op->inv; tmp->below; tmp=tmp->below)
  1758.       if (!tmp->invisible)
  1759.     if (i-- == j)
  1760.       head =tmp;
  1761.     tail =tmp;
  1762.   } else {
  1763.     for (tmp=op->inv; tmp->below; tmp=tmp->below)
  1764.       ;
  1765.     tail =tmp;
  1766.     for (i=0; tmp; tmp=tmp->above)
  1767.       if (!tmp->invisible)
  1768.     if (++i == j)
  1769.       break;
  1770.     head =tmp;
  1771.   }
  1772.   if (!head)
  1773.     return 0;
  1774.  
  1775.   tmp =op->inv;
  1776.   op->inv =head;
  1777.   head->above->below =NULL;
  1778.   head->above =NULL;
  1779.   tail->below =tmp;
  1780.   tmp->above =tail;
  1781.   
  1782.   if(QUERY_FLAG(op, FLAG_WIZ))
  1783.     sprintf(buf,"Rotate %d. The %s (%d) is now on top.",
  1784.             j, query_name(op->inv),op->inv->count);
  1785.   else
  1786.     sprintf(buf,"Rotate %d. The %s is now on top.", j, query_name(op->inv));
  1787.   new_draw_info(NDI_UNIQUE, 0,op,buf);
  1788.   draw_inventory(op);
  1789.       op->contr->count_left=0;
  1790.   return 0;
  1791. }
  1792.  
  1793. int command_invisible (object *op, char *params)
  1794. {
  1795.   if (!op)
  1796.     return 0;
  1797.       op->invisible+=100;
  1798.       update_object(op);
  1799.       new_draw_info(NDI_UNIQUE, 0,op,"You turn invisible.");
  1800.   return 0;
  1801. }
  1802.  
  1803. int command_rotateshoottype (object *op, char *params)
  1804. {
  1805.   if (!params)
  1806.       change_spell(op,'+');
  1807.   else
  1808.     change_spell(op, params[0]);
  1809.   return 0;
  1810. }
  1811.  
  1812. int command_show (object *op, char *params)
  1813. {
  1814.  
  1815.   if(!params) {
  1816.       if (++op->contr->show_what > show_nonmagical)
  1817.         op->contr->show_what = show_all;
  1818.       draw_all_inventory(op);
  1819.     return 1;
  1820.   }
  1821.  
  1822.   if (!strncmp(params, "all", strlen(params)))
  1823.     op->contr->show_what = show_all;
  1824.   else if (!strncmp(params, "applied", strlen(params)))
  1825.     op->contr->show_what = show_applied;
  1826.   else if (!strncmp(params, "unapplied", strlen(params)))
  1827.     op->contr->show_what = show_unapplied;
  1828.   else if (!strncmp(params, "unpaid", strlen(params)))
  1829.     op->contr->show_what = show_unpaid;
  1830.   else if (!strncmp(params, "cursed", strlen(params)))
  1831.     op->contr->show_what = show_cursed;
  1832.   else if (!strncmp(params, "magical", strlen(params)))
  1833.     op->contr->show_what = show_magical;
  1834.   else if (!strncmp(params, "nonmagical", strlen(params)))
  1835.     op->contr->show_what = show_nonmagical;
  1836.  
  1837.   draw_all_inventory(op);
  1838.   return 1;
  1839. }
  1840.  
  1841. int command_throw (object *op, char *params)
  1842. {
  1843.       new_draw_info(NDI_UNIQUE, 0,op,"Throw is disabled (it was too buggy).");
  1844. #if 0
  1845.       op->contr->shoottype=10;
  1846.       op->contr->count_left=0;
  1847.       new_draw_info(NDI_UNIQUE, 0,op,"You will now throw things.");
  1848. #endif
  1849.   return 0;
  1850. }
  1851.  
  1852. int command_brace (object *op, char *params)
  1853. {
  1854.   if (!params)
  1855.     op->contr->braced =!op->contr->braced;
  1856.   else
  1857.     op->contr->braced =onoff_value(params);
  1858.  
  1859.   if(op->contr->braced)
  1860.     new_draw_info(NDI_UNIQUE, 0,op, "You are braced.");
  1861.   else
  1862.     new_draw_info(NDI_UNIQUE, 0,op, "Not braced.");
  1863.  
  1864.       fix_player(op);
  1865.   return 0;
  1866. }
  1867.  
  1868. int command_rotatespells (object *op, char *params)
  1869. {
  1870.   player *pl=op->contr;
  1871.   int i, j;
  1872.  
  1873.   if(pl->shoottype != range_magic) {
  1874.     if(pl->nrofknownspells > 0) {
  1875.       pl->shoottype = range_magic;
  1876.       pl->chosen_spell = pl->known_spells[0];
  1877.     } else
  1878.           new_draw_info(NDI_UNIQUE, 0,op,"You know no spells.");
  1879.     return 0;
  1880.   }
  1881.  
  1882.   for(i=0;i<pl->nrofknownspells;i++)
  1883.     if(pl->known_spells[i]==pl->chosen_spell)
  1884.         {
  1885.     j =1;
  1886.     if(params)
  1887.       sscanf(params, "%d", &j);
  1888.     i +=j + (int)pl->nrofknownspells;
  1889.     i = i % (int)pl->nrofknownspells;
  1890.     pl->chosen_spell=pl->known_spells[i];
  1891.     draw_stats(op);
  1892.     return 1;
  1893.         }
  1894.   pl->chosen_spell=pl->known_spells[0];
  1895.   draw_stats(op);
  1896.   return 1;
  1897. }
  1898.  
  1899. #ifdef SAVE_WINDOW_POSITIONS
  1900. int command_savewinpos (object *op, char *params)
  1901. {
  1902.   player *pl=op->contr;
  1903.     int i,eq=1;
  1904.  
  1905.   if(!(pl->split_window)) {
  1906.       new_draw_info(NDI_UNIQUE, 0,op,"You can't save window positions in this mode.");
  1907.     return 0;
  1908.     }
  1909.   if(pl->valid_save_positions) {
  1910.     pl->valid_save_positions=0;
  1911.       new_draw_info(NDI_UNIQUE, 0,op,"Window positions will no longer be saved.");
  1912.     return 0;
  1913.     }
  1914.  
  1915.   get_window_coord(op,pl->win_game,
  1916.            &pl->win_pos[0].x,&pl->win_pos[0].y,
  1917.            &pl->win_pos[0].wx,&pl->win_pos[0].wy,
  1918.            &pl->win_pos[0].w,&pl->win_pos[0].h);
  1919.   get_window_coord(op,pl->win_stats,
  1920.            &pl->win_pos[1].x,&pl->win_pos[1].y,
  1921.            &pl->win_pos[1].wx,&pl->win_pos[1].wy,
  1922.            &pl->win_pos[1].w,&pl->win_pos[1].h);
  1923.   get_window_coord(op,pl->win_info,
  1924.            &pl->win_pos[2].x,&pl->win_pos[2].y,
  1925.            &pl->win_pos[2].wx,&pl->win_pos[2].wy,
  1926.            &pl->win_pos[2].w,&pl->win_pos[2].h);
  1927.   get_window_coord(op,pl->win_inv,
  1928.            &pl->win_pos[3].x,&pl->win_pos[3].y,
  1929.            &pl->win_pos[3].wx,&pl->win_pos[3].wy,
  1930.            &pl->win_pos[3].w,&pl->win_pos[3].h);
  1931.   get_window_coord(op,pl->win_look,
  1932.            &pl->win_pos[4].x,&pl->win_pos[4].y,
  1933.            &pl->win_pos[4].wx,&pl->win_pos[4].wy,
  1934.            &pl->win_pos[4].w,&pl->win_pos[4].h);
  1935.   get_window_coord(op,pl->win_message,
  1936.            &pl->win_pos[5].x,&pl->win_pos[5].y,
  1937.            &pl->win_pos[5].wx,&pl->win_pos[5].wy,
  1938.            &pl->win_pos[5].w,&pl->win_pos[5].h);
  1939.     for(i=0;i<5;i++)    /* try to figure out the window coords */
  1940.     if(pl->win_pos[i].x!=pl->win_pos[i+1].x ||
  1941.        pl->win_pos[i].y!=pl->win_pos[i+1].y)
  1942.         {
  1943.           eq=0;            /* window positions were different */
  1944.     return 0;
  1945.         }
  1946.     if(eq)            /* need to shift window positions (wm frame) */
  1947.       for(i=0;i<6;i++)
  1948.         {
  1949. #ifdef FUNNY_WINDOW_MANAGER /* try defining this if the other doesn't work */
  1950.     pl->win_pos[i].x=pl->win_pos[i].wx-
  1951.       pl->win_pos[i].x;
  1952.     pl->win_pos[i].y=pl->win_pos[i].wy-
  1953.       pl->win_pos[i].y;
  1954. #else /* FUNNY_WINDOW_MANAGER */
  1955.     pl->win_pos[i].x=pl->win_pos[i].wx;
  1956.     pl->win_pos[i].y=pl->win_pos[i].wy;
  1957. #endif /* FUNNY_WINDOW_MANAGER */
  1958.         }
  1959.     pl->valid_save_positions=1;
  1960.     new_draw_info(NDI_UNIQUE, 0,op,"Current window positions will be saved.");
  1961.         return 0;
  1962. }
  1963. #endif /* SAVE_WINDOW_POSITIONS */
  1964.  
  1965.